package com.lzs.flowable.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.Maps;
import com.lzs.common.dto.PageQuery;
import com.lzs.common.utils.BeanMapUtils;
import com.lzs.common.utils.UUIDUtils;
import com.lzs.common.vo.CommonResult;
import com.lzs.flowable.dto.FlowableProcdefStartDto;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.entity.ContentType;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.Model;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.image.impl.DefaultProcessDiagramGenerator;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

@RestController
@RequestMapping("flowableProcdef")
@Api(tags = "部署流程控制器")
public class FlowableProcdefController {

    @Resource
    private RepositoryService repositoryService;
    @Resource
    private RuntimeService runtimeService;
    @Resource
    private TaskService taskService;
    @Resource
    private ProcessEngine processEngine;
    @Resource
    private HistoryService historyService;

    @ApiOperation("列表")
    @GetMapping("getByPage")
    public CommonResult getByPage(PageQuery pageQuery){
        pageQuery.changePage();
        Integer pageNum = pageQuery.getPageNum();
        Integer pageSize = pageQuery.getPageSize();

        List<Deployment> deploymentList = repositoryService.createDeploymentQuery()
                .orderByDeploymentTime().desc()
                .listPage(pageNum, pageSize);
        long count = repositoryService.createDeploymentQuery().count();
        List<Map<String, Object>> mapList = BeanMapUtils.objectsToMaps(deploymentList);
        return CommonResult.rows(mapList,count);
    }
    @ApiOperation("删除")
    @DeleteMapping("deleteById/{id}")
    public CommonResult deleteById(@PathVariable String id){
        repositoryService.deleteDeployment(id);
        return CommonResult.OK();
    }

    @ApiOperation("获取流程图")
    @GetMapping("getFlowImg")
    public void getFlowImg(HttpServletResponse response,String deploymentId,String processInstanceId,String processDefinitionId){
        ProcessEngineConfiguration engConf = processEngine.getProcessEngineConfiguration();

        response.setHeader("Content-Type", ContentType.IMAGE_JPEG.toString());
        if (StringUtils.isBlank(processDefinitionId)) {
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                    .deploymentId(deploymentId)
                    .singleResult();
            processDefinitionId = processDefinition.getId();
        }

        List<String> highLightedActivities = new ArrayList<>();
        List<String> highLightedFlows = new ArrayList<>();

        if (StringUtils.isNotBlank(processInstanceId)) {
            // 获得活动的节点
            List<HistoricActivityInstance> highLightedActivityList = historyService.createHistoricActivityInstanceQuery()
                    .processInstanceId(processInstanceId)
                    .orderByHistoricActivityInstanceStartTime()
                    .asc()
                    .list();

            for (HistoricActivityInstance tempActivity : highLightedActivityList) {
                String activityId = tempActivity.getActivityId();
                highLightedActivities.add(activityId);
                if("sequenceFlow".equals(tempActivity.getActivityType())){
                    highLightedFlows.add(tempActivity.getActivityId());
                }
            }
        }


        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);

        ProcessDiagramGenerator diagramGenerator = engConf.getProcessDiagramGenerator();
        InputStream inputStream = diagramGenerator.generateDiagram(bpmnModel, "bmp", highLightedActivities, highLightedFlows, engConf.getActivityFontName(),
                engConf.getLabelFontName(), engConf.getAnnotationFontName(), engConf.getClassLoader(), 1.0, true);


        OutputStream out = null;
        try {
            out = response.getOutputStream();
            for (int b = -1; (b = inputStream.read()) != -1; ) {
                out.write(b);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (Objects.nonNull(out)) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (Objects.nonNull(inputStream)) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @ApiOperation("导入bpmn文件")
    @PostMapping("importBpmnFile")
    public CommonResult importBpmnFile(MultipartFile file){
        String bpmnName = "";
        String key = UUIDUtils.generateUUID();
        ZipInputStream zipInputStream = null;
        try {
            zipInputStream = new ZipInputStream(file.getInputStream());
            Deployment deploy = repositoryService.createDeployment()
                    //eclipse创建好的bpmn和png文件，放入resources下的processes文件夹中
                    .addZipInputStream(zipInputStream)
                    .key(key)
                    .category("default")
                    .name(key+"_name")
                    .deploy();
            String deployId = deploy.getId();
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                    .deploymentId(deployId)
                    .singleResult();
            if (Objects.nonNull(processDefinition)) {
                return CommonResult.OK();
            }else {
                repositoryService.deleteDeployment(deployId);
                return CommonResult.Err("导入失败，请检查文件");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (Objects.nonNull(zipInputStream)) {
                try {
                    while(zipInputStream.getNextEntry() != null){
                        zipInputStream.closeEntry();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    zipInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return CommonResult.Err("导入失败，请检查文件");
    }

    @ApiOperation("运行流程")
    @PostMapping("start")
    public CommonResult start(@RequestBody FlowableProcdefStartDto dto){
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .deploymentId(dto.getDeploymentId())
                .singleResult();
        ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinition.getId());
        processInstance.getProcessDefinitionId();
        return CommonResult.OK();
    }
}
